from app.db import db
from app.Models.HealthModels.FoodModels.FoodRecordModel import FoodRecord  # 导入你的模型
from app.Models.HealthModels.FoodModels.FoodCateModel import FoodCate  # 食物类型表模型（需确保存在）
from app.Models.AdminModels.UserModels.UserModel import User  # 用户表模型（需确保存在）
from app.Models.HealthModels.FoodModels.FoodCalModel import FoodCal  # 食物热量表模型（需确保存在）
from datetime import date, datetime


class FoodRecordDAO:
    """饮食摄入记录DAO层：负责数据库交互"""

    # -------------------------- 新增 --------------------------
    @staticmethod
    def add_food_record(food_cate_id, user_id, food_id, act_intake_gram, act_intake_kcal,
                        intake_date, note=None):
        """
        新增饮食摄入记录
        :param food_cate_id: 食物类型ID
        :param user_id: 用户ID
        :param food_id: 食物名称ID（关联food_cal表）
        :param act_intake_gram: 实际克重
        :param act_intake_kcal: 实际摄入热量（可根据食物单位热量×克重计算后传入）
        :param intake_date: 摄入日期（date类型或字符串，如"2025-11-03"）
        :param note: 备注（可选）
        :return: 新增的记录对象
        """
        # 处理日期参数（若传入字符串，转换为date类型）
        if isinstance(intake_date, str):
            intake_date = datetime.strptime(intake_date, '%Y-%m-%d').date()

        # 创建记录对象
        new_record = FoodRecord(
            food_cate_id=food_cate_id,
            user_id=user_id,
            food_id=food_id,
            act_intake_gram=act_intake_gram,
            act_intake_kcal=act_intake_kcal,
            intake_date=intake_date,
            submit_time=datetime.now(),  # 提交时间自动填充当前 datetime
            note=note
        )

        # 提交到数据库
        db.session.add(new_record)
        db.session.commit()
        return new_record

    # -------------------------- 删除 --------------------------
    @staticmethod
    def delete_food_record(record_id):
        """
        根据ID删除饮食记录
        :param record_id: 记录ID（主键）
        :return: True（删除成功）/ False（记录不存在）
        """
        record = FoodRecord.query.get(record_id)
        if not record:
            return False

        db.session.delete(record)
        db.session.commit()
        return True

    # -------------------------- 更新 --------------------------
    @staticmethod
    def update_food_record(record_id, **kwargs):
        """
        根据ID更新饮食记录（支持部分字段更新）
        :param record_id: 记录ID（主键）
        :param kwargs: 要更新的字段（如 food_id=123, act_intake_gram=200.0）
        :return: 更新后的记录对象 / None（记录不存在）
        """
        record = FoodRecord.query.get(record_id)
        if not record:
            return None

        # 处理日期字段（若传入字符串，转换为对应类型）
        if 'intake_date' in kwargs and isinstance(kwargs['intake_date'], str):
            kwargs['intake_date'] = datetime.strptime(kwargs['intake_date'], '%Y-%m-%d').date()
        if 'submit_time' in kwargs and isinstance(kwargs['submit_time'], str):
            kwargs['submit_time'] = datetime.strptime(kwargs['submit_time'], '%Y-%m-%d %H:%M:%S')

        # 批量更新字段
        for key, value in kwargs.items():
            if hasattr(record, key):  # 只更新模型中存在的字段
                setattr(record, key, value)

        db.session.commit()
        return record

    # -------------------------- 基础查询（不带关联名称） --------------------------
    @staticmethod
    def get_food_record_by_id(record_id):
        """根据ID查询单条记录"""
        return FoodRecord.query.get(record_id)

    @staticmethod
    def get_food_records_by_user(user_id, start_date=None, end_date=None):
        """
        根据用户ID查询记录（支持日期范围筛选）
        :param user_id: 用户ID
        :param start_date: 开始日期（如"2025-11-01"或date对象）
        :param end_date: 结束日期（如"2025-11-03"或date对象）
        :return: 记录列表
        """
        query = FoodRecord.query.filter_by(user_id=user_id)

        # 处理日期筛选
        if start_date:
            if isinstance(start_date, str):
                start_date = datetime.strptime(start_date, '%Y-%m-%d').date()
            query = query.filter(FoodRecord.intake_date >= start_date)
        if end_date:
            if isinstance(end_date, str):
                end_date = datetime.strptime(end_date, '%Y-%m-%d').date()
            query = query.filter(FoodRecord.intake_date <= end_date)

        # 按摄入日期+提交时间降序排列（最新记录在前）
        return query.order_by(FoodRecord.intake_date.desc(), FoodRecord.submit_time.desc()).all()

    @staticmethod
    def get_all_food_records(page=1, per_page=20):
        """
        分页查询所有记录（适用于管理员后台）
        :param page: 页码（默认第1页）
        :param per_page: 每页条数（默认20条）
        :return: Pagination对象（包含items列表、总页数等）
        """
        return FoodRecord.query.order_by(FoodRecord.submit_time.desc()).paginate(
            page=page, per_page=per_page, error_out=False
        )

    # -------------------------- 关联查询（带ID对应名称） --------------------------
    @staticmethod
    def get_food_record_with_names(record_id):
        """
        根据ID查询记录，包含关联表的名称（食物类型名、用户名、食物名称）
        :return: 字典（含基础字段 + 关联名称）/ None
        """
        # 多表联合查询（JOIN关联三个表）
        record = db.session.query(
            FoodRecord,  # 主表所有字段
            FoodCate.food_cate_name.label('food_cate_name'),  # 食物类型名称
            User.username.label('user_name'),  # 用户名（假设user表字段为username）
            FoodCal.food_name.label('food_name')  # 食物名称（假设food_cal表字段为name）
        ).join(
            FoodCate, FoodRecord.food_cate_id == FoodCate.id, isouter=True  # 外连接（避免记录丢失）
        ).join(
            User, FoodRecord.user_id == User.id, isouter=True
        ).join(
            FoodCal, FoodRecord.food_id == FoodCal.id, isouter=True
        ).filter(
            FoodRecord.id == record_id
        ).first()

        if not record:
            return None

        # 解析查询结果（record[0]是FoodRecord对象，后面是关联名称）
        food_record, food_cate_name, user_name, food_name = record
        base_dict = food_record.to_dict()
        # 添加关联名称字段
        base_dict.update({
            'food_cate_name': food_cate_name,  # 食物类型名称（如"蔬菜"）
            'user_name': user_name,  # 用户名（如"张三"）
            'food_name': food_name  # 食物名称（如"菠菜"）
        })

        # 格式化日期时间字段（确保统一格式）
        if base_dict.get('intake_date'):
            base_dict['intake_date'] = base_dict['intake_date'].strftime('%Y-%m-%d')
        return base_dict

    @staticmethod
    def get_food_records_by_user_with_names(user_id, start_date=None, end_date=None):
        """
        根据用户ID查询记录（带关联名称），支持日期范围筛选
        :return: 字典列表（每条记录含基础字段 + 关联名称）
        """
        query = db.session.query(
            FoodRecord,
            FoodCate.food_cate_name.label('food_cate_name'),
            User.username.label('user_name'),
            FoodCal.food_name.label('food_name')
        ).join(
            FoodCate, FoodRecord.food_cate_id == FoodCate.id, isouter=True
        ).join(
            User, FoodRecord.user_id == User.id, isouter=True
        ).join(
            FoodCal, FoodRecord.food_id == FoodCal.id, isouter=True
        ).filter(
            FoodRecord.user_id == user_id
        )

        # 日期筛选（同基础查询逻辑）
        if start_date:
            if isinstance(start_date, str):
                start_date = datetime.strptime(start_date, '%Y-%m-%d').date()
            query = query.filter(FoodRecord.intake_date >= start_date)
        if end_date:
            if isinstance(end_date, str):
                end_date = datetime.strptime(end_date, '%Y-%m-%d').date()
            query = query.filter(FoodRecord.intake_date <= end_date)

        # 排序
        records = query.order_by(FoodRecord.intake_date.desc(), FoodRecord.submit_time.desc()).all()

        # 转换为字典列表
        result = []
        for item in records:
            food_record, food_cate_name, user_name, food_name = item
            base_dict = food_record.to_dict()
            base_dict.update({
                'food_cate_name': food_cate_name,
                'user_name': user_name,
                'food_name': food_name
            })
            result.append(base_dict)

        return result
